Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(action menu): keyboard accessibility omnibus #5031

Open
wants to merge 69 commits into
base: main
Choose a base branch
from

Conversation

nikkimk
Copy link
Contributor

@nikkimk nikkimk commented Jan 16, 2025

Action menu items are not reading for screen readers.

Description

Action menu should be using a roving tabindex not aria-activedescendant because of cross-root ARIA limitations as well as lack of iOS support.

The sp-menu that action menu uses was refactored to use a roving tabindex, and the numpad keys fix that was made in action menu are now applied to the focus group controller which the roving tabindex controller uses.

Related issue(s)

Motivation and context

VoiceOver could not read the menu items when navigated via keyboard because of the cross-root aria issues above. Using the same roving tabindex controller that other components in our repo use, allows us to ensure roving tabindex and keyboard navigation is accessible and consistent across all components.

How has this been tested?

  • By default a Menu should follow the Navigation Menu Example from the WAI ARIA APG.
  • Menus with selects and menu groups should function like the menu groups in the Editor Menubar Example from the WAI ARIA APG
  • Please note that there will be VRT differences where open menus that didn't used to have focus now do. Menus that are opened via keyboard are supposed to set focus on a menu item.

Does screenreader read menuitems? (resolves #4556 and without regression on #3751)

  1. Go to https://nikkimk-fix-menu-a11y--spectrum-web-components.netlify.app/components/action-menu/#sizes
  2. Open Voice Over
  3. Tab to the More Actions... menu button.
  4. Press Down Arrow repeatedly to scroll through the menu items
  5. Press Up Arrow repeatedly to scroll through the menu items
  6. Press Numpad Down Arrow repeatedly to and scroll through the menu items
  7. Press Numpad Up Arrow repeatedly to and scroll through the menu items
  8. Screenreader should read menu items

Can you use a screenreader to click a menuitem? (resolves #4997)

  1. Go to https://nikkimk-fix-menu-a11y--spectrum-web-components.netlify.app/components/action-menu/#sizes
  2. Open Voice Over
  3. Tab to the menuitem.
  4. Tab focus to the button.
  5. Press CRTL+Option+Space to click the link.
  6. Link should be activated.

Does keyboard navigation of menuitems work as it should? (closes #4557)

  1. Go to this WAI ARIA APG Menu Button example.
  2. Click on the Actions menu button.
  3. Notice that the menu opens and focus is on the first item.
  4. Press Down Arrow.
  5. Notice that the focus is on the second item.
  6. Now go to https://nikkimk-fix-menu-a11y--spectrum-web-components.netlify.app/storybook/iframe.html?args=&id=action-menu--default&viewMode=story
  7. Click on the More Actions... menu button.
  8. Notice that the menu opens and focus is on the first item.
  9. Press Down Arrow.
  10. Notice that the focus is on the second item.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • [] Breaking change (fix or feature that would cause existing functionality to change) _This change will affect combobox, but combobox was already inaccessible. See RFC for Accessible Menu navigation for more information. _
  • Chore (minor updates related to the tooling or maintenance of the repository, does not impact compiled assets)

Checklist

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • If my change required a change to the documentation, I have updated the documentation in this pull request.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices

Best practices

This repository uses conventional commit syntax for each commit message; note that the GitHub UI does not use this by default so be cautious when accepting suggested changes. Avoid the "Update branch" button on the pull request and opt instead for rebasing your branch against main.

@nikkimk nikkimk linked an issue Jan 16, 2025 that may be closed by this pull request
1 task
Copy link

changeset-bot bot commented Jan 16, 2025

🦋 Changeset detected

Latest commit: d163634

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

Branch preview

Review the following VRT differences

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

Copy link

Tachometer results

Currently, no packages are changed by this PR...

Copy link

github-actions bot commented Jan 16, 2025

Lighthouse scores

Category Latest (report) Main (report) Branch (report)
Performance 0.99 0.98 0.99
Accessibility 1 1 1
Best Practices 1 1 1
SEO 1 0.92 0.92
PWA 1 1 1
What is this?

Lighthouse scores comparing the documentation site built from the PR ("Branch") to that of the production documentation site ("Latest") and the build currently on main ("Main"). Higher scores are better, but note that the SEO scores on Netlify URLs are artifically constrained to 0.92.

Transfer Size

Category Latest Main Branch
Total 249.755 kB 234.757 kB 234.604 kB 🏆
Scripts 62.159 kB 54.43 kB 54.405 kB 🏆
Stylesheet 51.511 kB 45.761 kB 🏆 45.774 kB
Document 6.223 kB 5.502 kB 5.462 kB 🏆
Font 127.012 kB 126.653 kB 126.613 kB 🏆

Request Count

Category Latest Main Branch
Total 52 52 52
Scripts 41 41 41
Stylesheet 5 5 5
Document 1 1 1
Font 2 2 2

@coveralls
Copy link
Collaborator

coveralls commented Jan 16, 2025

Pull Request Test Coverage Report for Build 13318379084

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 446 of 491 (90.84%) changed or added relevant lines in 10 files are covered.
  • 25 unchanged lines in 6 files lost coverage.
  • Overall coverage decreased (-0.2%) to 97.993%

Changes Missing Coverage Covered Lines Changed/Added Lines %
tools/reactive-controllers/src/FocusGroup.ts 24 25 96.0%
packages/picker/src/MobileController.ts 3 5 60.0%
packages/picker/src/Picker.ts 103 107 96.26%
packages/menu/src/Menu.ts 163 171 95.32%
packages/menu/src/MenuItem.ts 122 136 89.71%
packages/action-menu/src/ActionMenu.ts 12 28 42.86%
Files with Coverage Reduction New Missed Lines %
packages/picker/src/InteractionController.ts 2 94.07%
packages/tabs/src/Tabs.ts 2 98.34%
packages/picker/src/DesktopController.ts 2 90.83%
tools/shared/src/focusable.ts 2 99.32%
packages/menu/src/Menu.ts 8 94.46%
packages/picker/src/Picker.ts 9 97.21%
Totals Coverage Status
Change from base Build 13290469074: -0.2%
Covered Lines: 33228
Relevant Lines: 33714

💛 - Coveralls

@@ -436,56 +436,6 @@ export const testActionMenu = (mode: 'sync' | 'async'): void => {

expect(firstRect).to.deep.equal(secondRect);
});
it('opens and selects in a single pointer button interaction', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Menu hover was removed for better a11y experience, so this test is no longer needed

@@ -91,12 +90,7 @@ describe('Action Menu - Groups', () => {
press: 'ArrowDown',
});
await opened;
expect(el.open).to.be.true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When opened, menu should focus on the first selected item, so we don't need to ArrowUp to focus on it

@@ -45,18 +45,17 @@ export class RovingTabindexController<
}

manageTabindexes(): void {
if (this.focused) {
if (this.focused && !this.delegatesFocus) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we want to look at the components that use these controllers to see if they are following WAI ARIA APG for keyboard nav, but in the meantime, so we don't have scope-creep on this PR, I'm allowing existing components to still follow this pattern.

@@ -353,48 +353,6 @@ describe('Tabs', () => {
await elementUpdated(el);
expect(el.selected).to.be.equal('first');
});
it('prevents [tabindex=0] while `focusin`', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tab panels should not have a tabindex. This test is failing but is not needed.

@@ -102,55 +98,26 @@ describe('Combobox accessibility', () => {
)) as unknown as AccessibleNamedNode & {
children: AccessibleNamedNode[];
};

// WebKit doesn't currently associate the `name` via the accessibility tree.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The time to get rid of the escape hatch is now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants